iT邦幫忙

2022 iThome 鐵人賽

DAY 6
0
Software Development

你知道Go是什麼嗎?系列 第 6

Day6 - 結構與方法 - Golang

  • 分享至 

  • xImage
  •  

耶來到第六天了,為了介紹方便有調整了一下原先的介紹順序。今天就介紹結構跟方法,提到指標的部分可以先隨意讀一下,明天會再詳細說。

結構(struct)

與C語言一樣,Go語言承襲了這個傳統,可使用struct來自定義複合物件,可依照使用需要自行定義物件結構。

結構(struct)是使用者定義的類型,包含了變數命名/型態的一個集合。用於將相關數據組合在一起以形成單個單元。可以用結構來表達現實世界任何擁有屬性的實體。

定義結構

type structName struct{}

type student struct {
    name string
    height float64
}

使用type來宣告一種新的型別(結構),在這例子中以student為例,該型別存有兩個屬性(attribute),分別為姓名和身高。

宣告結構

應該算三種或四種?ab兩種宣告法差在有沒有使用取址符號&a是指向變數,b是指向變數位址,在使用時要注意,以免在參數傳遞時型態出錯。

取值或更改值可直接使用「.」來操作,很方便ˊˇˋ

func main() {
    a := student{name: "Morris", height: 176.1}
    b := &student{"Furry", 163.5}

    c := new(student)
    c.name = "BenLee"
    c.height = 169.9

    var d student
    d.name = ("Thomas")
    d.height = 175.8
}

匿名結構

func main(){
    p := struct{
        name string
        height float64
    }{name: "Jim", height:170.1}
	
    fmt.Println(p.name)
    fmt.Println(p.height)
}

output:

Jim 170.1

關聯結構

在一個struct內可以包含另一個struct

type Student struct {
    name string
    height float64
    contact contactInfo
}
type contactInfo struct {
    email string
    phoneNumber string
}

func main() {
	info1 := contactInfo{"mark123@mail.com", "0912345678"}
	stu1 := &Student{"Mark", 178.1, info1}

	fmt.Printf("%+v\n\n", stu1)
	fmt.Println("name:", stu1.name, "height:", stu1.height)
	fmt.Println("mail:", stu1.email)
	fmt.Println("phone:", stu1.phoneNumber)

}

output:

&{name:Mark height:178.1 contactInfo:{email:mark123@mail.com phoneNumber:0912345678}}

name: Mark height: 178.1
mail: mark123@mail.com
phone: 0912345678

仔細看會發現,我在使用StudentcontactInfoemail時,只使用了stu1.email,因為在Go結構內的參數與方法是可以直接從最外層取用到的。

方法 (method)

Go does not have classes. However, you can define methods on types.

A method is a function with a special receiver argument.

與物件導向程式不同,Go不會在class內寫method,而是利用receiver來實作method,詳情看程式碼應該比較好懂

方法宣告

範例為Student增加一個名為getInfo()的方法。

type Student struct {
    name string
    height float64
}

func (s Student) getInfo(){
    fmt.Println("Student Name:", s.name)
    fmt.Println("Height:" , s.height , "cm.")
}

func main() {
    s1 := Student{"Morris", 176.4}
    s1.getInfo()
}
  1. 中間的(s Student),為Student添加一個receiver function
  2. getInfo是函式名稱
  3. main當中執行s1.getInfo()時,這邊s1就是func(s Student)中的s

上面程式碼等於為了Student這個類別寫了一個方法,所有Student類別的物件都可以使用getInfo方法。

Pointer receivers

若是要更改傳入參數的值,則需要使用Pointer receivers的方式寫函式,否則無法修改到實例的資料,先介紹錯誤範例ˊˇˋ

func (s Student) getHeight() {
	fmt.Println("Height:", s.height, "cm.")
}
func (s Student) setHeight(h float64) {
	s.height = h
	fmt.Println("After set, height is", s.height, "cm.")
}
func main() {
	s1 := Student{"Morris", 176.4}
	s1.setHeight(177.0) //set success
	s1.getHeight() //Height: 176.4 cm.
}

看以上這個範例,我明明呼叫了s1.setHeight(177.0),但實際height並沒有被更動到。因此在做變更數值的動作時,要使用指標做為reciever,下方程式碼為有使用Pointer receivers的。

func (s Student) getHeight() {
	fmt.Println("Height:", s.height, "cm.")
}
func (s *Student) setHeight(h float64) { // 更動這行
	s.height = h
	fmt.Println("set success")
}
func main() {
	s1 := Student{"Morris", 176.4}
	s1.setHeight(177.0)
	s1.getHeight() //Height: 177 cm.
}

使用(s *Student)做方法宣告,在變更資料時才會改到傳入的struct

仔細看會發現我是直接使用s1.setHeight,是因為在Go中會自動將s1.setHeight()看成(&s1).setHeight()


今天就介紹到這吧,functionmethod都介紹完,先進入指標再介紹程式流程,基礎的部分也快告一段落了讚讚。

參考資料

[Golang] function & method 函式與方法
https://pjchender.dev/golang/function-and-method/

Golang Structs Tutorial with Examples
https://www.callicoder.com/golang-structs/

[Golang] Struct
https://pjchender.dev/golang/structs/

tags: Golang

上一篇
Day5 - 函式(function)- Golang
下一篇
Day7 - Pointer - Golang
系列文
你知道Go是什麼嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言